package com.jeomo.base.provider.handler;

import com.jeomo.common.core.exception.BusinessException;
import com.jeomo.common.core.result.CommonResult;
import com.jeomo.common.core.result.ResultCode;
import com.jeomo.common.core.vo.ParameterInvalidItem;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;

/**
 * @Author: qbt
 * @Date: 2019/4/10 23:24
 * @Version 1.0
 */

@RestController
@ControllerAdvice
public class BaseGlobalExceptionHandler {

    private Logger log = LoggerFactory.getLogger(BaseGlobalExceptionHandler.class);

    /**
     * 处理验证参数封装错误时异常
     */
    @ExceptionHandler
    protected CommonResult handleConstraintViolationException(HttpMessageNotReadableException e, HttpServletRequest request) {
        log.info("handleConstraintViolationException start, uri:{}, caused by: ", request.getRequestURI(), e);
        return CommonResult.failure(ResultCode.PARAM_IS_INVALID.code(), ResultCode.PARAM_IS_INVALID.msg());
    }

    /**
     * 处理参数绑定时异常（反400错误码）
     */
    @ExceptionHandler
    protected CommonResult handleBindException(BindException e, HttpServletRequest request) {
        log.info("handleBindException start, uri:{}, caused by: ", request.getRequestURI(), e);
        List<ParameterInvalidItem> parameterInvalidItemList = convertBindingResultToMapParameterInvalidItemList(e.getBindingResult());
        return CommonResult.failure(ResultCode.PARAM_IS_INVALID.code(), ResultCode.PARAM_IS_INVALID.msg());
    }

    /**
     * 处理使用@Validated注解时，参数验证错误异常（反400错误码）
     */
    @ExceptionHandler
    protected CommonResult handleMethodArgumentNotValidException(MethodArgumentNotValidException e, HttpServletRequest request) {
        log.info("handleMethodArgumentNotValidException start, uri:{}, caused by: ", request.getRequestURI(), e);
        List<ParameterInvalidItem> parameterInvalidItemList = convertBindingResultToMapParameterInvalidItemList(e.getBindingResult());
        return CommonResult.failure(ResultCode.PARAM_IS_INVALID.code(), ResultCode.PARAM_IS_INVALID.msg());
    }

    /**
     * 处理通用自定义业务异常
     */
    @ExceptionHandler
    protected CommonResult handleBusinessException(BusinessException e, HttpServletRequest request) {
        log.info("handleBusinessException start, uri:{}, exception:{}, caused by: {}", request.getRequestURI(), e.getClass(), e.getMessage());
        return CommonResult.failure(e.getCode(), e.getMessage());
    }

//    /**
//     * 处理运行时系统异常（反500错误码）
//     */
//    @ExceptionHandler
//    protected CommonResult handleRuntimeException(RuntimeException e, HttpServletRequest request) {
//        log.error("handleRuntimeException start, uri:{}, caused by: ", request.getRequestURI(), e);
//        return CommonResult.failure(ResultCode.SYSTEM_INNER_ERROR.code(), ResultCode.SYSTEM_INNER_ERROR.msg());
//    }

    //    public static List<ParameterInvalidItem> convertCVSetToParameterInvalidItemList(Set<ConstraintViolation<?>> cvset) {
//        if (cvset == null || cvset.size() == 0) {
//            return null;
//        }
//        List<ParameterInvalidItem> parameterInvalidItemList = new ArrayList<>();
//        for (ConstraintViolation<?> cv : cvset) {
//            ParameterInvalidItem parameterInvalidItem = new ParameterInvalidItem();
//            String propertyPath = cv.getPropertyPath().toString();
//            if (propertyPath.indexOf(".") != -1) {
//                String[] propertyPathArr = propertyPath.split("\\.");
//                parameterInvalidItem.setFieldName(propertyPathArr[propertyPathArr.length - 1]);
//            } else {
//                parameterInvalidItem.setFieldName(propertyPath);
//            }
//            parameterInvalidItem.setMessage(cv.getMessage());
//            parameterInvalidItemList.add(parameterInvalidItem);
//        }
//
//        return parameterInvalidItemList;
//    }

    private static List<ParameterInvalidItem> convertBindingResultToMapParameterInvalidItemList(BindingResult bindingResult) {
        if (bindingResult == null) {
            return null;
        }
        List<ParameterInvalidItem> parameterInvalidItemList = new ArrayList<>();
        List<FieldError> fieldErrorList = bindingResult.getFieldErrors();
        for (FieldError fieldError : fieldErrorList) {
            ParameterInvalidItem parameterInvalidItem = new ParameterInvalidItem();
            parameterInvalidItem.setFieldName(fieldError.getField());
            parameterInvalidItem.setMessage(fieldError.getDefaultMessage());
            parameterInvalidItemList.add(parameterInvalidItem);
        }

        return parameterInvalidItemList;
    }

}
